use std::{rc::Rc, cell::RefCell, sync::{mpsc::Sender, Arc, Mutex}};

use crate::{cmd::Cmd, rtda::{heap::{self, ClassLoader, string_pool, Class}, self, Object, Frame}, classpath::Classpath, instructions::base, interpreter::interpret, native, SenderType};




pub struct JVM {
    cmd: Cmd,
    class_loader: Arc<Mutex<ClassLoader>>,
    main_thread: Arc<Mutex<rtda::Thread>>,
    sender: Option<Sender<SenderType>>, // JVM 持有rust主线程的sender
}

impl JVM {
    pub fn new_jvm(cmd: Cmd, sender: Sender<SenderType>) -> JVM {
        let cp = Classpath::parse(&cmd.x_jre_opthin, &cmd.cp_option);
        let class_loader = heap::ClassLoader::new_class_loader(cp, cmd.verbose_class_flag);
        JVM {
            cmd: cmd,
            class_loader: class_loader.clone(),
            main_thread: rtda::Thread::new_main_thread(class_loader, None),
            sender: Some(sender),
        }
    }

    pub fn start(&mut self) {
        // 初始化本地方法，暂时放到这里执行。
        native::init();
        self.init_vm();
        self.exec_main();
    }

    fn init_vm(&mut self) {
        let vm_class = self.class_loader.lock().unwrap().load_class("sun/misc/VM".to_string());
        base::init_class(self.main_thread.clone(), vm_class);
        // interpret(self.main_thread.clone(), self.cmd.verbose_inst_falg);
        interpret(self.main_thread.clone(), false);
        // println!("init vm end");
    }

    fn exec_main(&mut self) {
        let class_name = self.cmd.class.replace(".", "/");
        let main_class = self.class_loader.lock().unwrap().load_class(class_name);
        let main_method = unsafe { &*main_class }.get_main_method();
        if main_method.is_none() {
            println!("Main method not found in class {}", self.cmd.class);
            return;
        }
        let args_arr = self.create_args_array();

        let frame = Frame::new_frame(self.main_thread.clone(), main_method.unwrap());
        // 给main方法传递args参数
        frame.get_local_vars().borrow_mut().set_ref(0, Some(Box::into_raw(Box::new(args_arr))));
        self.main_thread.lock().unwrap().push_frame(frame);
        interpret(self.main_thread.clone(), self.cmd.verbose_inst_falg);
        // println!("main end");
    }

    // 字符串常量池目前存在thread里，多加个thread参数
    fn create_args_array(&self) -> Object {
        let string_class = self.class_loader.lock().unwrap().load_class("java/lang/String".to_string());
        let args = &self.cmd.args;
        let args_len = self.cmd.args.len();
        let arr_class = string_class.array_class();
        let mut args_arr = Class::new_array(arr_class, args_len);
        if let rtda::heap::ArrayObject::Object(j_args) = args_arr.array() {
            for i in 0..args.len() {
                let arg = &args[i];
                j_args[i] = Some(string_pool::j_string(&mut self.class_loader.clone().lock().unwrap(), arg));
            }
        }
        args_arr
    }

    pub fn main_thread(&self) -> Arc<Mutex<rtda::Thread>> {
        self.main_thread.clone()
    }

    pub fn take_sender(&mut self) -> Option<Sender<SenderType>> {
        self.sender.take()
    }
}